home *** CD-ROM | disk | FTP | other *** search
/ Hot Super Models / Hot Super Models.iso / unix / x11 / xv200.tar / xv-2.00 / xvsunras.c < prev    next >
C/C++ Source or Header  |  1992-01-01  |  11KB  |  440 lines

  1. /*
  2.  * xvsunras.c - load routine for 'sun rasterfile' format pictures
  3.  *
  4.  * LoadSunRas(fname, numcols)  -  loads a PM pic, does 24to8 code if nec.
  5.  * WriteSunRas(fp, pic, w, h, r,g,b, numcols, style)
  6.  * WriteRaw(fp, pic, w, h, r,g,b, numcols, style)
  7.  *
  8.  * This file written by Dave Heath (heath@cs.jhu.edu)
  9.  * fixBGR() added by Ken Rossman (ken@shibuya.cc.columbia.edu)
  10.  */
  11.  
  12.  
  13. #include "xv.h"
  14. #include "sunras.h"
  15.  
  16. static int  SunRasError();
  17. static int  rle_read();
  18. static void flipl();
  19. static void SunRas1to8();
  20. static void SunRas8to1();
  21. static int  write_sun_long();
  22. static void fixBGR();
  23.  
  24.  
  25. /*******************************************/
  26. int LoadSunRas(fname,nc)
  27.      char *fname;
  28.      int   nc;
  29. /*******************************************/
  30. {
  31.   FILE    *fp;
  32.   int     linesize,lsize,csize,isize,flipit,i,w,h,d,rv;
  33.   byte     *image, *line;
  34.   struct rasterfile sunheader;
  35.  
  36.   rv = 0;
  37.  
  38.   /* read in the Sun Rasterfile picture */
  39.   fp=fopen(fname,"r");
  40.   if (!fp) return( SunRasError("unable to open file") );
  41.  
  42.   flipit = 0;
  43.   fread(&sunheader,sizeof(struct rasterfile),1,fp);
  44.   if (sunheader.ras_magic != RAS_MAGIC)
  45.   {
  46.     flipl( (byte *) &sunheader.ras_magic);
  47.     if (sunheader.ras_magic == RAS_MAGIC) flipit = 1;
  48.     else flipl( (byte *) &sunheader.ras_magic);
  49.   }
  50.   if (sunheader.ras_magic != RAS_MAGIC) 
  51.     return( SunRasError("not a Sun rasterfile") );
  52.  
  53.   if (flipit) {
  54.     flipl((byte *) &sunheader.ras_width);
  55.     flipl((byte *) &sunheader.ras_height);
  56.     flipl((byte *) &sunheader.ras_depth);
  57.     flipl((byte *) &sunheader.ras_length);
  58.     flipl((byte *) &sunheader.ras_type);
  59.     flipl((byte *) &sunheader.ras_maptype);
  60.     flipl((byte *) &sunheader.ras_maplength);
  61.     }
  62.  
  63.   /* make sure that the input picture can be dealt with */
  64.   if (sunheader.ras_depth != 1 &&
  65.       sunheader.ras_depth != 8 &&
  66.       sunheader.ras_depth != 24) {
  67.     fprintf (stderr, "Sun rasterfile image has depth %d\n", 
  68.          sunheader.ras_depth);
  69.     fprintf (stderr, "Depths supported are 1, 8, and 24\n");
  70.     return 1;
  71.   }
  72.  
  73.   if (sunheader.ras_type != RT_OLD &&
  74.       sunheader.ras_type != RT_STANDARD &&
  75.       sunheader.ras_type != RT_BYTE_ENCODED &&
  76.       sunheader.ras_type != RT_FORMAT_RGB) {
  77.     fprintf (stderr, "Sun rasterfile of unsupported type %d\n",
  78.          sunheader.ras_type);
  79.     return 1;
  80.   }
  81.  
  82.   if (sunheader.ras_maptype != RMT_RAW &&
  83.       sunheader.ras_maptype != RMT_NONE &&
  84.       sunheader.ras_maptype != RMT_EQUAL_RGB) {
  85.     fprintf (stderr, "Sun rasterfile colormap of unsupported type %d\n",
  86.          sunheader.ras_maptype);
  87.     return 1;
  88.   }
  89.  
  90.   w = sunheader.ras_width;
  91.   h = sunheader.ras_height;
  92.   d = sunheader.ras_depth;
  93.   isize = sunheader.ras_length ?
  94.       sunheader.ras_length :
  95.       (w * h * d) / 8;
  96.   csize = (sunheader.ras_maptype == RMT_NONE) ? 0 : sunheader.ras_maplength;
  97.   lsize = w * h * ( d == 1 ? d : d/8);
  98.   linesize = w * d;
  99.   /* if ((linesize % 48) && d == 24) linesize += (48 - (linesize % 48)); */
  100.   if (linesize % 16) linesize += (16 - (linesize % 16));
  101.   linesize /= 8;
  102.  
  103.   if (DEBUG)
  104.   {
  105.     fprintf(stderr,"%s: LoadSunRas() - loading a %dx%d pic, %d planes\n",
  106.         cmd, w, h,
  107.         d);
  108.     fprintf (stderr, 
  109.        "type %d, maptype %d, isize %d, csize %d, lsize %d, linesize %d\n",
  110.          sunheader.ras_type, sunheader.ras_maptype,
  111.          isize, csize, lsize, linesize);
  112.   }
  113.  
  114.  
  115.   SetDirRButt(F_FORMAT, F_SUNRAS);
  116.   if (d==1) SetDirRButt(F_COLORS, F_BWDITHER);
  117.        else SetDirRButt(F_COLORS, F_FULLCOLOR);
  118.  
  119.   SetISTR(ISTR_FORMAT,"Sun %s rasterfile.  (%d plane%s)  (%d bytes)",
  120.       sunheader.ras_type == RT_BYTE_ENCODED ? "rle" : "standard",
  121.       d,
  122.       d == 1 ? "" : "s",
  123.       sizeof (struct rasterfile) + csize + isize);
  124.  
  125.   sprintf(formatStr, "%dx%d Sun Rasterfile.",w,h);
  126.  
  127.   /* read in the colormap, if any */
  128.   if (sunheader.ras_maptype == RMT_EQUAL_RGB && csize)
  129.   {
  130.     fread (r, sizeof (byte), sunheader.ras_maplength/3, fp);
  131.     fread (g, sizeof (byte), sunheader.ras_maplength/3, fp);
  132.     fread (b, sizeof (byte), sunheader.ras_maplength/3, fp);
  133.  
  134.    /* for (i = 0; i < sunheader.ras_maplength/3; i++)
  135.     {
  136.       r[i] = getc (fp);
  137.       g[i] = getc (fp);
  138.       b[i] = getc (fp);
  139.     } */
  140.   }
  141.   else if (sunheader.ras_maptype == RMT_RAW && csize)
  142.   {
  143.     /* we don't know how to handle raw colormap, ignore */
  144.     fseek (fp, (long) csize, 1);
  145.   }
  146.  
  147.   else {  /* no colormap, make one up */
  148.     if (sunheader.ras_depth == 1) {
  149.       r[0] = g[0] = b[0] = 0;
  150.       r[1] = g[1] = b[1] = 255;
  151.     }
  152.  
  153.     else if (sunheader.ras_depth == 8) {
  154.       for (i = 0; i < 256; i++)
  155.     r[i] = g[i]  = b[i] = i;
  156.     }
  157.   }
  158.  
  159.  
  160.   /* allocate memory for picture and read it in */
  161.   /* note we may slightly overallocate here (if image is padded) */
  162.   image = (byte *) malloc (lsize);
  163.   line = (byte *) malloc (linesize);
  164.   if (image == NULL || line == NULL)
  165.     FatalError("Can't allocate memory for image\n");
  166.  
  167.   for (i = 0; i < h; i++) {
  168.     if ((i&0x1f) == 0) WaitCursor();
  169.     if (sunheader.ras_type == RT_BYTE_ENCODED) {
  170.       if (rle_read (line, 1, linesize, fp, (i==0)) != linesize) break;
  171.     /* return (SunRasError ("rle file read error")); */
  172.     }
  173.  
  174.     else {
  175.       if (fread (line, 1, linesize, fp) != linesize)
  176.     return (SunRasError ("file read error"));
  177.     }
  178.  
  179.     switch (d) {
  180.     case 1:  SunRas1to8 (image + w * i, line, w);    break;
  181.     case 8:  memcpy (image + w * i, line, w);        break;
  182.     case 24: memcpy (image + w * i * 3, line, w * 3); break;
  183.     }
  184.   }
  185.  
  186.   if (fp != stdin) fclose (fp);
  187.   if (DEBUG) fprintf(stderr,"Sun ras: image loaded!\n");
  188.  
  189.   if (d == 24) {
  190.     if (sunheader.ras_type != RT_FORMAT_RGB) fixBGR(image,w,h);
  191.     rv = Conv24to8 (image, w, h, nc);
  192.     free (image);
  193.     return (rv);
  194.   }
  195.  
  196.   else {
  197.     pic = image;
  198.     pWIDE = w;
  199.     pHIGH = h;
  200.     return (0);
  201.   }
  202. }
  203.  
  204.  
  205. /*****************************/
  206. static int rle_read (ptr, size, nitems, fp, init)
  207. byte *ptr;
  208. int size, nitems,init;
  209. FILE *fp;
  210. {
  211.   static int count, ch;
  212.   int readbytes, c, read;
  213.  
  214.   if (init) { count = ch = 0; }
  215.  
  216.   readbytes = size * nitems;
  217.   for (read = 0; read < readbytes; read++) {
  218.     if (count) {
  219.       *ptr++ = (byte) ch;
  220.       count--;
  221.     }
  222.  
  223.     else {
  224.       c = getc(fp);
  225.       if (c == EOF) break;
  226.  
  227.       if (c == RAS_RLE) {   /* 0x80 */
  228.     count = getc(fp);
  229.     if (count == EOF) break;
  230.  
  231.     if (count < 0) count &= 0xff;
  232.     if (count == 0) *ptr++ = c;
  233.         else {
  234.           if ((ch = getc(fp)) == EOF) break;
  235.           *ptr++ = ch;
  236.         }
  237.       }
  238.       else *ptr++ = c;
  239.     }
  240.   }
  241.  
  242.   return (read/size);
  243. }
  244.  
  245.  
  246. /*****************************/
  247. static int SunRasError(st)
  248. char *st;
  249. {
  250.   SetISTR(ISTR_WARNING,"LoadSunRas() - %s",st);
  251.   Warning();
  252.   return -1;
  253. }
  254.  
  255.  
  256. /*****************************/
  257. static void flipl(p)
  258.      byte *p;
  259. {
  260.   byte t;
  261.   t = p[0];  p[0]=p[3];  p[3] = t;
  262.   t = p[1];  p[1]=p[2];  p[2] = t;
  263. }
  264.  
  265.  
  266. static void SunRas1to8 (dest, src, len)
  267. byte *dest, *src;
  268. int len;
  269. {
  270.   int i, b;
  271.   int c;
  272.  
  273.   for (i = 0, b = -1; i < len; i++) {
  274.     if (b < 0) {
  275.       b = 7;
  276.       c = ~*src++;
  277.     }
  278.     *dest++ = ((c >> (b--)) & 1);
  279.   }
  280. }
  281.  
  282.  
  283.  
  284. static void SunRas8to1 (dest, src, len)
  285. byte *dest, *src;
  286. int len;
  287. {
  288.   int i, b;
  289.   int c;
  290.  
  291.   for (c = b = i = 0; i < len; i++) {
  292.     c <<= 1;
  293.     c |= (*src++ ? 0 : 1);
  294.     if (b++ == 7) {
  295.       *dest++ = c;
  296.       b = c = 0;
  297.     }
  298.   }
  299.   if (b) *dest = c;
  300. }
  301.  
  302.  
  303.  
  304.  
  305. /*******************************************/
  306. int WriteSunRas(fp,pic,w,h,rmap,gmap,bmap,numcols,colorstyle,userle)
  307. FILE *fp;
  308. byte *pic;
  309. int   w,h;
  310. byte *rmap, *gmap, *bmap;
  311. int   numcols, colorstyle, userle;
  312. {
  313.   /* writes a sun rasterfile to the already open stream
  314.      writes either 8-bit or 1-bit (never 24)
  315.      currently will not write rle files
  316.  
  317.      biggest problem w/ rle file: should we compute
  318.      image size first (nicer) or go back and write it
  319.      in when we are done (kludgy)?
  320.    */
  321.  
  322.   struct rasterfile sunheader;
  323.   int linesize, i, color, d, y;
  324.   byte *line;
  325.  
  326.   if (colorstyle != 2 && numcols > 2) d = 8;
  327.   else d = 1;
  328.  
  329.   linesize = w;
  330.   if (d == 1) {
  331.     if (linesize % 8) linesize += (8 - linesize % 8);
  332.     linesize /= 8;
  333.   }
  334.  
  335.   if (linesize % 2) linesize++;
  336.   line = (byte *) malloc (linesize);
  337.   if (!line) {
  338.     SetISTR(ISTR_WARNING, "Can't allocate memory for save!\n");
  339.     return (1);
  340.   }
  341.  
  342.   if (DEBUG)
  343.     fprintf (stderr,
  344.          "WriteSunRas: d %d, linesize %d numcols %d\n",
  345.          d, linesize, numcols);
  346.  
  347.   /* set up the header */
  348.   sunheader.ras_magic      = RAS_MAGIC;
  349.   sunheader.ras_width      = w;
  350.   sunheader.ras_height      = h;
  351.   sunheader.ras_depth      = d;
  352.   sunheader.ras_length      = linesize * h;
  353.   sunheader.ras_type      = RT_STANDARD;
  354.   sunheader.ras_maptype   = (d == 1) ? RMT_NONE : RMT_EQUAL_RGB;
  355.   sunheader.ras_maplength = (d == 1) ? 0 : 3 * numcols;
  356.  
  357.   write_sun_long (sunheader.ras_magic     , fp);
  358.   write_sun_long (sunheader.ras_width     , fp);
  359.   write_sun_long (sunheader.ras_height     , fp);
  360.   write_sun_long (sunheader.ras_depth     , fp);
  361.   write_sun_long (sunheader.ras_length     , fp);
  362.   write_sun_long (sunheader.ras_type     , fp);
  363.   write_sun_long (sunheader.ras_maptype  , fp);
  364.   write_sun_long (sunheader.ras_maplength, fp);
  365.  
  366.   /* write the colormap */
  367.   if (d > 1)
  368.     if (colorstyle == 1)  /* grayscale */
  369.       for (color = 0; color < 3; color++)
  370.     for (i = 0; i < numcols; i++)
  371.       putc (MONO(rmap[i],gmap[i],bmap[i]), fp);
  372.     else {
  373.       fwrite (rmap, sizeof (byte), numcols, fp);
  374.       fwrite (gmap, sizeof (byte), numcols, fp);
  375.       fwrite (bmap, sizeof (byte), numcols, fp);
  376.     }
  377.  
  378.   /* write the image */
  379.   line[linesize-1] = 0;
  380.   for (y = 0; y < h; y++) {
  381.     if ((y&0x1f) == 0) WaitCursor();
  382.  
  383.     if (d > 1)
  384.       memcpy (line, pic + y * w, w);
  385.     else
  386.       SunRas8to1 (line, pic + y * w, w);
  387.  
  388.     if (fwrite (line, sizeof (byte), linesize, fp) != linesize) {
  389.       SetISTR(ISTR_WARNING, "Write failed during save!\n");
  390.       free (line);
  391.       return (2);
  392.     }
  393.   }
  394.  
  395.   free (line);
  396.   return (0);
  397. }
  398.  
  399.  
  400. /* write a long word in sun byte-order
  401.    returns 0 for success, EOF for failure
  402.  */
  403. static int write_sun_long (l, fp)
  404. long l;
  405. FILE *fp;
  406. {
  407.     char c;
  408.  
  409.     c = ((l >> 24) & 0xff);
  410.     if (putc (c, fp) == EOF) return (EOF);
  411.     c = ((l >> 16) & 0xff);
  412.     if (putc (c, fp) == EOF) return (EOF);
  413.     c = ((l >> 8) & 0xff);
  414.     if (putc (c, fp) == EOF) return (EOF);
  415.     c = (l & 0xff);
  416.     if (putc (c, fp) == EOF) return (EOF);
  417.     return (0);
  418. }
  419.  
  420.  
  421.  
  422.  
  423. /* kr3 - fix up BGR order SUN 24-bit rasters to be RGB order */
  424. static void fixBGR(img,w,h)
  425. unsigned char *img;
  426. int w,h;
  427. {
  428.   int i,npixels;
  429.   unsigned char tmp;
  430.  
  431.   npixels = w*h;
  432.   for (i=0; i<npixels; i++) {
  433.     tmp = img[0];                   /* swap red and blue channels */
  434.     img[0] = img[2];
  435.     img[2] = tmp;
  436.     img += 3;                       /* bump to next pixel */
  437.   }
  438. }
  439.  
  440.